package com.mathdroid.model.simulation;

import java.util.HashMap;
import java.util.LinkedList;

/**
 * This contains information about a simulation or consolidates a group of
 * simulations.
 */
public final class SimulationStatistics 
extends HashMap<String, AbilityStatistics> {

	/**
	 * Generated UID.
	 */
	private static final long serialVersionUID = -3492402308289922426L;
	
	/**
	 * Merge the statistics list. After the merge this contains the merged
	 * <b>average</b> results.
	 * @param list A list of statistics.
	 */
	public void merge(final LinkedList<SimulationStatistics> list) {
		final int size = list.size();
		
		/* Fill this Hash with keys and clean values */
		for (String ability : list.get(0).keySet()) {
			this.put(ability, new AbilityStatistics());
		}
		
		for (SimulationStatistics s : list) {
			for (String ability : s.keySet()) {
				this.get(ability).addCrits(s.get(ability).getCrits());
				this.get(ability).addHits(s.get(ability).getHits());
				this.get(ability).addMisses(s.get(ability).getMisses());
				this.get(ability).addDirectDamage(
						s.get(ability).getDirectDamage());
				this.get(ability).addDirectHealing(
						s.get(ability).getDirectHealing());
				this.get(ability).addPeriodicDamage(
						s.get(ability).getPeriodicDamage());
				this.get(ability).addPeriodicHealing(
						s.get(ability).getPeriodicHealing());
				this.get(ability).addCosts(
						s.get(ability).getCosts());
				this.get(ability).addUses(
						s.get(ability).getUses());
			}
		}
		
		this.calculateAverages(size);
	}

	/**
	 * Calculate the averages of the values.
	 * @param d The divisor.
	 */
	public void calculateAverages(final int d) {

		for (String ability : this.keySet()) {
			this.get(ability).setCrits(this.get(ability).getCrits() / d);
			this.get(ability).setHits(this.get(ability).getHits() / d);
			this.get(ability).setMisses(this.get(ability).getMisses() / d);
			this.get(ability).setDirectDamage(
					this.get(ability).getDirectDamage() / d);
			this.get(ability).setDirectHealing(
					this.get(ability).getDirectHealing() / d);
			this.get(ability).setPeriodicDamage(
					this.get(ability).getPeriodicDamage() / d);
			this.get(ability).setPeriodicHealing(
					this.get(ability).getPeriodicHealing() / d);
			this.get(ability).setCosts(
					this.get(ability).getCosts() / d);
			this.get(ability).setUses(
					this.get(ability).getUses() / d);
		}
	}
	
	@Override
	public AbilityStatistics get(final Object key) {
		
		if (!this.containsKey(key)) {
			this.put((String) key, new AbilityStatistics());
		}
		
		return super.get(key);
	}
	
	@Override
	public String toString() {
		String s = new String();
		
		for (String ability : this.keySet()) {
			s = s.concat("\n\nAbility:\t\t" + ability);
			s = s.concat("\nDirect Damage:\t\t" 
					+ this.get(ability).getDirectDamage());
			s = s.concat("\nPeriodic Damage:\t" 
					+ this.get(ability).getPeriodicDamage());
			s = s.concat("\nDirect Healing:\t\t" 
					+ this.get(ability).getDirectHealing());
			s = s.concat("\nPeriodic Healing:\t" 
					+ this.get(ability).getPeriodicHealing());
			s = s.concat("\nHits:\t\t\t" 
					+ this.get(ability).getHits());
			s = s.concat("\nCriticals:\t\t" 
					+ this.get(ability).getCrits());
			s = s.concat("\nMisses:\t\t\t" 
							+ this.get(ability).getMisses());
			s = s.concat("\nUses:\t\t\t" 
					+ this.get(ability).getUses());
			s = s.concat("\nResource Costs:\t\t" 
					+ this.get(ability).getCosts());
		}
		
		return s;
	}
}
